home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 52
/
Amiga Format AFCD52 (Issue 136, May 2000).iso
/
-in_the_mag-
/
multitasking
/
monitors
/
top
/
top.c
< prev
next >
Wrap
C/C++ Source or Header
|
2000-03-05
|
23KB
|
1,293 lines
#define VERSION "2.0 "
#define EARLIEST_LIB 37 /* 2.04 and above */
/* *INDENT-OFF* */
/********************************************************************
*
* Name: Top
*
*
* Function:
*
* A program, similar to the UNIX 'top', which displays a list of
* Tasks/Process's showing their relative CPU-usage as a percentage.
*
*
* Implemention:
*
* It puts a wedge in front of Exec's Switch() and records the
* execution time of the task/process invoked.
*
* The display is refreshed every 5 seconds, and lists items in
* descending order of usage, i.e. usage hogs are at the "top".
*
* Runs on AmigaDos 2.04 and above.
*
*
*
***** Written by Gary Duncan
*
* 57 Melbourne Hill Rd
* Warrandyte << bell-birds live here :-)
* Vic 3113
* Australia
*
* E-mail: gduncan@werple.net.au
*
*
***** Freely distributable for non-commercial purposes.
* Please keep this header intact.
*
*
* Compiles under SAS 6.x
*
* Formatted with 'indent -gnu' ; a big time-saving program.
*
*
*
* Acknowledgements:-
*
*
* 1) Gunther Nikl for explaining how Xoper does it (Thanks, Gunther)
* ( and to Werner Gunther for writing the original Xoper)
*
* 2) Beta-testers; thanks everyone ...
*
*========================================================================
Timo Karjalainen tikarjal@raita.oulu.fi
Everett M. Greene mojaveg@ridgecrest.ca.us
Johan Thelmin jth@kuai.se
Andy Savage andy@epma.demon.co.uk
Donald J. Maddox dmaddox@scsn.net
Innovision Concepts Ltd keith@innov.demon.co.uk
Laurent Papier papier@dpt-info.u-strasbg.fr
Infinite Dreams rahamans@cs.man.ac.uk
Johan Alfredsson d95duvan@dtek.chalmers.se
Petri Nordlund petrin@walrus.megabaud.fi
Allan Duncan a.duncan@trl.telstra.com.au
(no relation :)
Rene Mendoza mendoza@cmc1.coloradomtn.edu
Michal Rybaski mryba@mcs.com
*========================================================================
*
* 3) ... and to C= ; I used chunks of their Console handler code
* from the RKRM C-examples.
*
*
********************************************************************/
/*** Function List
myswitch (void)
main (int argc, char **argv)
build_tsk (void)
build_tsk_item (TOP * tsk_ptr, TASK * t_ptr, int t_num, UBYTE flag)
copy_task_name (TOP * tsk_ptr, char *ptr)
get_proc_name (PROCESS * p_ptr)
my_qsort (void *ptr, int no, int sz, int (*func) ())
my_cmp (void *p1, void *p2)
open_timer (void)
start_timer (int secs)
deleteTimer (TIMEREQUEST * xt_req)
open_console (void)
con_cleanup (void)
openConsole (IOSTDREQ * writereq, IOSTDREQ * readreq, WINDOW * window)
closeConsole (IOSTDREQ * writereq)
conPuts (IOSTDREQ * writereq, UBYTE * string)
conRead (IOSTDREQ * readreq, UBYTE * whereto, int len)
con_win_event (void)
get_win_size (int *x, int *y)
move_cursor (int x, int y)
fatal_err (char *z)
hexit (char *ptr)
usage (void)
***/
/* *INDENT-ON* */
/**** ****/
#define TASK_NAME_LEN 25
#define TASK_PROC_LEN 10
#define SAMPLE_SECS 5
#include "top.h"
extern __far ULONG (*oldswitch) (void);
extern __far ULONG wrapper (void);
void __regargs __chkabort (void);
void __regargs
__chkabort (void)
{
}
typedef struct
{
int t_no;
int t_calls;
long t_eticks;
TASK *t_task;
int t_taskpri;
BOOL t_isaCLI;
char t_type;
char t_name[TASK_NAME_LEN + 1];
int t_name_len;
char t_task_proc[TASK_PROC_LEN + 1];
}
TOP;
#include "proto/top_protos.h"
/*
* string for AmigaDOS Version Command
*/
static char A_vers[] = "$VER: top\t" VERSION __AMIGADATE__;
static char *what_who = "Top (%s) - written by gduncan@werple.net.au";
static char *hdr =
{"\x1B[1\x1B[7;31;40m\
NO TYPE NAME PRI CALLS SECS USAGE STATE \
\x1B[0;31;40m\n"
};
int my_cmp (void *p1, void *p2);
LIBRARY *TimerBase = NULL;
static TIMEREQUEST *t_req;
static MSGPORT *timerport;
static ULONG e_freq;
#define NTASKS 100
int max_lines;
TOP tlist_a[NTASKS];
TOP tlist_b[NTASKS];
TOP *t_cur;
TOP *t_prev;
TASK *task_list[NTASKS];
static ECLOCKVAL ecl_now;
static ECLOCKVAL ecl_last;
static EXECBASE *ExecBase;
TASK *this_task;
TASK *t_ptr;
int last_sort_count;
int this_sort_count;
int sort_flag;
int t_offs;
ULONG delta;
int task_count;
int task_count_new;
int task_pri = -1;
ECLOCKVAL *ecv;
int not_found;
int eclock;
char title[80];
BOOL g_switch = FALSE;
int sample_time = SAMPLE_SECS;
ULONG e_ticks;
ULONG e_ticks_temp;
ULONG e_ticks_then;
//==================================================
SCREEN scr;
NEWWINDOW nw =
{
0, 0, /* starting position (left,top) */
640, 200, /* width, height */
(UBYTE) - 1, (UBYTE) - 1, /* detailpen, blockpen */
CLOSEWINDOW | NEWSIZE, /* flags for idcmp */
WINDOWDEPTH | WINDOWSIZING |
WINDOWDRAG | WINDOWCLOSE |
SMART_REFRESH | ACTIVATE | NEWSIZE, /* window flags */
NULL, /* no user gadgets */
NULL, /* no user checkmark */
title,
NULL, /* pointer to window screen */
NULL, /* pointer to super bitmap */
640, 50, /* min width, height */
640, 500, /* max width, height */
WBENCHSCREEN /* open on workbench screen */
};
LIBRARY *IntuitionBase = NULL;
WINDOW *win = NULL;
IOSTDREQ *Con_writeReq = NULL; /* I/O request block pointer */
MSGPORT *Con_writePort = NULL; /* replyport for writes */
IOSTDREQ *Con_readReq = NULL; /* I/O request block pointer */
MSGPORT *Con_readPort = NULL; /* replyport for reads */
BOOL OpenedConsole = FALSE;
INTUIMESSAGE *winmsg;
ULONG signals;
UBYTE och;
BYTE oc_error;
/*
********************************************************-
*/
/*
* SetFunc'd into Switch(); called by asm stub, wrapper()
*
* - this is the code which accumulates task run time.
*
*/
void __asm __saveds __interrupt
myswitch (void)
{
BOOL found = FALSE;
t_offs = 0;
t_ptr = (TASK *) ExecBase->ThisTask;
/*
* search list for this task
*/
for (t_offs = 0; t_offs < task_count;)
{
if (t_cur[t_offs].t_task == t_ptr)
{
found = TRUE;
break;
}
if (++t_offs == NTASKS)
{
++not_found;
return; /* too many tasks... */
}
} /*for */
/*
* new task, add to list
*/
if (found == FALSE)
{
build_tsk_item (&t_cur[t_offs], t_ptr, t_offs);
++task_count;
}
/*
* increment e-ticks used for this task...
*/
eclock = ReadEClock (&ecl_now);
delta = ecl_now.ev_lo - ecl_last.ev_lo;
t_cur[t_offs].t_eticks += delta;
t_cur[t_offs].t_calls++;
ecl_last = ecl_now;
}
/*
********************************************************-
*/
void
main (int argc, char **argv)
{
int k;
ULONG wait_mask;
ULONG retval;
LONG m_timer;
LONG m_window;
LONG m_console;
int my_notfound;
int total_ticks;
char con_buf[200];
TOP *tp;
int time;
int usage_percent;
int usage_dot_percent;
int secs;
int msecs;
char *ptr;
char buf_usage[40];
char buf_secs[60];
/*
* check for -t option
*/
if (argc > 1)
{
BOOL flag = FALSE;
if (*(ptr = argv[1]) == '-')
{
if (*++ptr == 't')
{
sample_time = atoi (++ptr);
if (sample_time < 1)
{
fprintf (stderr, "Bad time value\n");
}
else
{
flag = TRUE;
}
}
}
if (flag == FALSE)
{
usage ();
exit (0);
}
}
ExecBase = *(EXECBASE **) 4;
this_task = (TASK *) ExecBase->ThisTask;
sprintf (title, what_who, VERSION);
open_timer ();
open_console ();
eclock = ReadEClock (&ecl_last);
/*
* create Wait mask (timer, Console Read , and Write)
*/
m_timer = 1 << timerport->mp_SigBit;
m_console = 1 << Con_readPort->mp_SigBit;
m_window = 1 << win->UserPort->mp_SigBit;
wait_mask = m_timer | m_console | m_window;
e_ticks_then = start_timer (1); /* quick start first up */
t_cur = tlist_a;
/*
* build list of active tasks
*/
task_count = build_tsk_array (t_cur);
for (;;)
{
/*
* patch exec's Switch() to ours...
*/
if (g_switch != TRUE)
{
Forbid ();
{
oldswitch = (ULONG (*)(void)) SetFunction ((LIBRARY *) ExecBase,
-54, wrapper);
g_switch = TRUE;
}
Permit ();
}
/*
* soak up time busy waiting for signals at lowest priority...
*/
for (;;)
{
task_pri = SetTaskPri (this_task, -127);
{
while ((retval = (this_task->tc_SigRecvd & wait_mask)) == 0);
}
SetTaskPri (this_task, task_pri); /* up priority again... */
Disable ();
{
this_task->tc_SigRecvd &= (~retval);
}
Enable ();
if (retval & m_console)
{
/* future use ? */
retval &= ~m_console;
}
if (retval & m_window)
{
retval &= ~m_window;
if (con_win_event () == TRUE) /* window activity */
{
hexit ("");
}
}
if ((retval & (~wait_mask)) != 0)
{
sprintf (con_buf, "Invalid signal bit (%08X)\n", retval);
hexit (con_buf); /*invalid */
}
if (retval & m_timer)
{
retval &= ~m_timer;
GetMsg (timerport); /* timer */
break; /* get out of look to print report */
}
}
Disable ();
{
my_notfound = not_found;
not_found = 0;
total_ticks = 0;
/*
* switch arrays
*/
if (t_cur == tlist_a)
{
t_cur = tlist_b;
t_prev = tlist_a;
}
else
{
t_cur = tlist_a;
t_prev = tlist_b;
}
/*
* build new list of active tasks
*/
task_count_new = build_tsk_array (t_cur);
}
Enable ();
/*
* restart timer; get actual elapsed Eticks
*/
e_ticks_temp = start_timer (sample_time);
e_ticks = e_ticks_temp - e_ticks_then;
e_ticks_then = e_ticks_temp;
/*
* sort task list in descending order of t_eticks
*/
my_qsort (t_prev, task_count, sizeof (TOP), my_cmp);
task_count = task_count_new;
move_cursor (1, 1); /* cursor to home */
conPuts (Con_writeReq, hdr); /* write header */
/*
*===============================================================
*
* ! now print report, task by task ...
*
*===============================================================
*/
for (k = 0; k < max_lines; ++k)
{
tp = &t_prev[k];
/*
* ignore empty slots (task has gone)
*/
if (tp->t_task == (TASK *) 0)
continue;
time = tp->t_eticks;
/*
* if time = 0 , just print spaces...
*/
if (time == 0)
{
strcpy (buf_usage, " ");
strcpy (buf_secs, " "); /*ss.mmm */
}
else
{
secs = time / eclock;
msecs = (time % eclock) / 1000;
usage_dot_percent = (((time * 100) % e_ticks) * 10) / e_ticks;
usage_percent = (time * 100) / e_ticks;
/*
* inc to avoid printing all zeros (a "white lie" :) ...
*/
if ((secs + msecs) == 0)
msecs = 1;
if ((usage_percent + usage_dot_percent) == 0)
++usage_dot_percent;
sprintf (buf_secs, "%2d.", secs);
sprintf (&buf_secs[3], "%03d", msecs);
sprintf (buf_usage, "%2d.", usage_percent);
sprintf (&buf_usage[3], "%d%%", usage_dot_percent);
}
/*
* build this tasks report line ...
*/
sprintf (con_buf, "%2d %s %-23s %4d %4d %s %s %s\n",
k,
tp->t_task_proc,
tp->t_name,
tp->t_taskpri,
tp->t_calls,
buf_secs,
buf_usage,
get_state (t_cur, tp->t_task));
/*
* ... and write it to the Console
*/
conPuts (Con_writeReq, con_buf);
total_ticks += tp->t_eticks;
tp->t_eticks = 0;
tp->t_calls = 0;
}
/*
* erase to end of display ( ... since a task may have gone)
*/
conPuts (Con_writeReq, "\x9B\x4A");
}
hexit ("");
}
/*
*********************************************************************
*/
char *
get_state (TOP * t_ptr, TASK * task_ptr)
{
char *r_val = "<gone>";
static char buf[10];
int j = 0;
TASK *p;
while (p = t_ptr[j].t_task)
{
if (p == task_ptr)
{
switch (p->tc_State)
{
case 2:
r_val = "run ";
break;
case 3:
r_val = "ready ";
break;
case 4:
r_val = "wait ";
break;
default:
sprintf (buf, "%6d", p->tc_State);
r_val = buf;
break;
}
}
++j;
}
return (r_val);
}
/*
*********************************************************************
*/
int
build_tsk_array (TOP * t_ptr)
{
int tsk_no;
NODE *node;
memset (t_ptr, sizeof(t_ptr[NTASKS]), 0);
tsk_no = 0;
Forbid ();
{
build_tsk_item (&t_ptr[tsk_no], this_task, tsk_no);
++tsk_no;
/*
* scan Wait list
*/
for (node = ExecBase->TaskWait.lh_Head;
node->ln_Succ; node = node->ln_Succ)
{
build_tsk_item (&t_ptr[tsk_no], (TASK *) node, tsk_no);
++tsk_no;
}
/*
* scan Ready list
*/
for (node = ExecBase->TaskReady.lh_Head;
node->ln_Succ; node = node->ln_Succ)
{
build_tsk_item (&t_ptr[tsk_no], (TASK *) node, tsk_no);
++tsk_no;
}
}
Permit ();
return (tsk_no);
}
/*
*********************************************************************
*/
void
build_tsk_item (TOP * tsk_ptr, TASK * t_ptr, int t_num)
{
char cli_name[40];
char *ptr_name = t_ptr->tc_Node.ln_Name;
PROCESS *p_ptr = (PROCESS *) t_ptr;
tsk_ptr->t_no = t_num;
tsk_ptr->t_calls = 0;
tsk_ptr->t_eticks = 0;
tsk_ptr->t_task = t_ptr;
tsk_ptr->t_taskpri = t_ptr->tc_Node.ln_Pri;
tsk_ptr->t_type = t_ptr->tc_Node.ln_Type;
tsk_ptr->t_isaCLI = FALSE;
ptr_name = t_ptr->tc_Node.ln_Name;
tsk_ptr->t_name_len = strlen (ptr_name);
/*
* construct Task/Process field
*/
if (tsk_ptr->t_type == 1)
{
/*
* its a Task...
*/
strcpy (tsk_ptr->t_task_proc, "Task ");
}
else
{
/*
* its a Process...
*/
int pr_num = p_ptr->pr_TaskNum;
/*
* check if CLI...
*/
if (pr_num == 0)
{
sprintf (tsk_ptr->t_task_proc, "Proc ");
}
else
{
char *p_name;
tsk_ptr->t_isaCLI = TRUE;
sprintf (tsk_ptr->t_task_proc, "Proc[%2d] ", pr_num);
/*
* CLI; build command name
*/
p_name = get_proc_name (p_ptr);
sprintf (cli_name, "[ %s ]", p_name);
ptr_name = cli_name;
tsk_ptr->t_name_len = strlen (p_name);
}
}
copy_task_name (tsk_ptr, ptr_name);
}
/*
*********************************************************************
*/
void
copy_task_name (TOP * tsk_ptr, char *ptr)
{
int j;
for (j = 0; j < TASK_NAME_LEN; ++j)
{
UBYTE cc = *ptr++;
if (cc == 0xA9)
cc = 0;
tsk_ptr->t_name[j] = cc;
if (cc == '\0')
break;
}
tsk_ptr->t_name[j] = '\0';
}
/*
*********************************************************************
*/
char *
get_proc_name (PROCESS * p_ptr)
{
COMMANDLINEINTERFACE *p_cli = BADDR (p_ptr->pr_CLI);
char *ptr;
int len;
/*
* if it's a CLI command, use it as task name
*/
if (p_cli->cli_Module != 0)
{
ptr = BADDR (p_cli->cli_CommandName);
len = *ptr++;
ptr[len] = '\0';
}
else
{
ptr = ((TASK *) p_ptr)->tc_Node.ln_Name;
}
return (ptr);
}
/*
*********************************************************************
*/
BOOL
my_qsort (void *ptr, int no, int sz, int (*func) ())
{
last_sort_count = this_sort_count;
this_sort_count = 0;
qsort (ptr, no, sz, func);
if (last_sort_count == this_sort_count)
return TRUE;
else
return FALSE;
}
/*
*********************************************************************
*/
int
my_cmp (void *p1, void *p2)
{
int retval;
retval = ((TOP *) p2)->t_eticks - ((TOP *) p1)->t_eticks;
if (retval > 0)
++this_sort_count;
return retval;
}
/*
*********************************************************************
*/
void
open_timer (void)
{
if ((timerport = CreatePort ("TOP", 0)) == NULL)
{
fatal_err ("Timer Port create failure\n");
}
if ((t_req = (TIMEREQUEST *) CreateExtIO ((MSGPORT *) timerport,
sizeof (TIMEREQUEST))) == NULL)
{
fatal_err ("Couldn't CreateExtIO in open_timer()\n");
}
if (OpenDevice (TIMERNAME, UNIT_VBLANK, (IOREQUEST *) t_req, 0L) != 0)
{
fatal_err ("Couldn't open VBLANK Timer\n");
}
TimerBase = (LIBRARY *) t_req->tr_node.io_Device;
}
/*
*********************************************************************
*/
ULONG
start_timer (int secs)
{
ECLOCKVAL ecl;
/*
* set up timer request
*/
t_req->tr_node.io_Message.mn_ReplyPort = timerport;
t_req->tr_node.io_Command = TR_ADDREQUEST;
t_req->tr_node.io_Flags = 0;
t_req->tr_node.io_Error = 0;
t_req->tr_time.tv_secs = secs;
t_req->tr_time.tv_micro = 0;
SendIO ((IOREQUEST *) & t_req->tr_node);
/*
* return current Eclock time
*/
ReadEClock (&ecl);
return (ecl.ev_lo);
}
/*
*********************************************************************
*/
void
deleteTimer (TIMEREQUEST * xt_req)
{
if (CheckIO ((IOREQUEST *) xt_req) == 0)
{
AbortIO ((IOREQUEST *) xt_req);
WaitIO ((IOREQUEST *) xt_req);
}
CloseDevice ((IOREQUEST *) xt_req);
DeleteExtIO ((IOREQUEST *) xt_req);
if (timerport)
DeletePort (timerport);
}
/*
*********************************************************************
*/
void
open_console (void)
{
int x;
if (!(IntuitionBase = OpenLibrary ("intuition.library", EARLIEST_LIB)))
{
hexit ("Can only run on AmigaDos 2.04 and above\n");
}
/*
* calculate max number of lines
*/
if (GetScreenData (&scr, sizeof (scr), WBENCHSCREEN, NULL) == FALSE)
{
hexit ("GetScreenData() fail\n");
}
else
{
if (scr.Height >= 400)
{
max_lines = 32;
nw.Height = 400; /* NTSC default */
}
else if (scr.Height >= 200)
{
max_lines = 14;
nw.Height = 200;
}
else
{
hexit ("Screen too small\n");
}
}
/*
* Create reply port and io block for writing to console
*/
if (!(Con_writePort = CreatePort ("top.console.write", 0)))
{
hexit ("Can't create write port\n");
}
if (!(Con_writeReq = (IOSTDREQ *)
CreateExtIO (Con_writePort, (LONG) sizeof (IOSTDREQ))))
{
hexit ("Can't create write request\n");
}
/*
* Create reply port and io block for reading from console
*/
if (!(Con_readPort = CreatePort ("top.console.read", 0)))
{
hexit ("Can't create read port\n");
}
if (!(Con_readReq = (IOSTDREQ *)
CreateExtIO (Con_readPort, (LONG) sizeof (IOSTDREQ))))
{
hexit ("Can't create read request\n");
}
/*
* Open a window
*/
if (!(win = OpenWindow (&nw)))
{
hexit ("OpenWindow() fail\n");
}
/*
* Now, attach a console to the window
*/
if (oc_error = openConsole (Con_writeReq, Con_readReq, win))
{
hexit ("Can't open console.device\n");
}
else
{
OpenedConsole = TRUE;
}
/*
* get size of window (cols, rows)
*/
get_win_size (&x, &max_lines);
}
/*
*********************************************************************
*/
void
con_cleanup (void)
{
if (Con_readReq)
{
if (!(CheckIO ((IOREQUEST *) Con_readReq)))
{
AbortIO ((IOREQUEST *) Con_readReq);
WaitIO ((IOREQUEST *) Con_readReq);
}
}
if (OpenedConsole)
closeConsole (Con_writeReq);
if (win)
CloseWindow (win);
if (Con_readReq)
DeleteExtIO ((IOREQUEST *) Con_readReq);
if (Con_readPort)
DeletePort (Con_readPort);
if (Con_writeReq)
DeleteExtIO ((IOREQUEST *) Con_writeReq);
if (Con_writePort)
DeletePort (Con_writePort);
if (IntuitionBase)
CloseLibrary (IntuitionBase);
}
/*
*********************************************************************
*/
BYTE
openConsole (IOSTDREQ * writereq, IOSTDREQ * readreq, WINDOW * window)
{
BYTE open_error;
writereq->io_Data = (APTR) window;
writereq->io_Length = sizeof (WINDOW);
open_error = OpenDevice ("console.device", 0, (IOREQUEST *) writereq, 0);
readreq->io_Device = writereq->io_Device; /* clone required parts */
readreq->io_Unit = writereq->io_Unit;
return (open_error);
}
/*
*********************************************************************
*/
void
closeConsole (IOSTDREQ * writereq)
{
CloseDevice ((IOREQUEST *) writereq);
}
/*
*********************************************************************
*/
/*
* Output a NULL-terminated string of characters to a console
*/
void
conPuts (IOSTDREQ * writereq, UBYTE * string)
{
writereq->io_Command = CMD_WRITE;
writereq->io_Data = (APTR) string;
writereq->io_Length = -1; /* means print till terminating null */
DoIO ((IOREQUEST *) writereq);
}
/*
*********************************************************************
*/
/*
* Queue up a read request to console, passing it pointer
* to a buffer into which it can read the string
*/
void
conRead (IOSTDREQ * readreq, UBYTE * whereto, int len)
{
readreq->io_Command = CMD_READ;
readreq->io_Data = (APTR) whereto;
readreq->io_Length = len;
DoIO ((IOREQUEST *) readreq);
}
/*
*********************************************************************
*/
int
con_win_event (void)
{
int flag = FALSE;
int x;
int class;
while (winmsg = (INTUIMESSAGE *) GetMsg (win->UserPort))
{
class = winmsg->Class;
switch (class)
{
case CLOSEWINDOW:
flag = TRUE;
break;
case NEWSIZE:
/*
* recalculate max lines, chars in resized window
*/
get_win_size (&x, &max_lines);
break;
default:
break;
}
ReplyMsg ((MESSAGE *) winmsg);
}
return (flag);
}
/*
*********************************************************************
*/
void
get_win_size (int *x, int *y)
{
char buf[12];
/*
* request new window size
*/
conPuts (Con_writeReq, "\033[0 \x71");
/*
* examine response, and get x,y (cols, rows)
*/
conRead (Con_readReq, buf, sizeof (buf));
*x = atoi (&buf[8]);
*y = atoi (&buf[5]) - 2;
}
/*
*********************************************************************
*/
void
move_cursor (int x, int y)
{
static char buf[10];
sprintf (buf, "\x9B%d;%d\x48", y, x);
conPuts (Con_writeReq, buf);
}
/*
*********************************************************************
*/
void
fatal_err (char *z)
{
fprintf (stderr, "ERROR: %s\n", z);
hexit ("");
}
/*
*********************************************************************
*/
void
hexit (char *ptr)
{
if (task_pri != -1)
SetTaskPri (this_task, task_pri);
if (*ptr != '\0')
printf ("%s", ptr);
/*
* reset Switch() vector
*/
if (g_switch == TRUE)
{
Forbid ();
{
(ULONG (*)(void)) SetFunction ((LIBRARY *) ExecBase, -54, oldswitch);
}
Permit ();
}
deleteTimer (t_req);
con_cleanup ();
exit (0);
}
/*
*********************************************************************
*/
void
usage (void)
{
fprintf (stderr, "\
top (version %s): Written by gduncan@werple.net.au\n\n\
Prints task usage as a relative %% over sample period, which is\n\
5 secs, or changeable via -t option.\n\
Usage: top [-tnn]\n\
\n\
-t nn = sample time in secs (default = 5)\n",
VERSION);
}